/*
* (C) Copyright 2013 Philip Kirchhoff 
* 
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
*-------------------------------------------------------------------------------
* This file is part of the DataLogger library by Philip Kirchhoff
* https://code.google.com/p/pk-data-logger/
* SVN: http://pk-data-logger.googlecode.com/svn/trunk
*-------------------------------------------------------------------------------
* Module    : DlFileWriter.cpp   
* Author    : Kirchhoff, Philip
* Date      : 01.04.2013
*-------------------------------------------------------------------------------
* Function definitions for class DlFileWriter
*   
*-------------------------------------------------------------------------------
* Change History:
* 01.04.2013  Kirchhoff 	Created
--------------------------------------------------------------------------------
*/

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdexcept>

#include "DlFileWriter.h"
#include "DlDataset.h"
#include "DlDataChannel.h"

using namespace std;

DlFileWriter::DlFileWriter(const char *fileName)
    : DlFileHandler(fileName)
{
}

DlFileWriter::~DlFileWriter()
{
}

void DlFileWriter::writeData()
{
    if(!mpDataSet)
    {
        string excStr(__PRETTY_FUNCTION__);
        excStr += ": No dataset specified";
        throw runtime_error(excStr.c_str());
    }

    if(mFileFormat == FILE_FORMAT_CSV_STD)
        writeCsvStdFile();
}

void DlFileWriter::writeCsvStdFile()
{
    if(!mpDataSet)
        return;

    // Open File
    ofstream outFile;
    string fName = mFileName+".csv";
    outFile.open(fName.c_str(),
                 ios_base::out | ios_base::trunc);

    // File open?
    if(!outFile.is_open())
    {
        string excStr(__PRETTY_FUNCTION__);
        excStr += ": Could not open " + fName;
        throw runtime_error(excStr.c_str());
    }

    // Write format identifier
    outFile << "CSV_STD_V1" << endl;

    // Write Channel Info
    outFile << "NUM_CHAN=" << mpDataSet->numChannnels() << endl;

    // Write channel IDs
    outFile << "sample;" << "timestamp;";
    for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
    {
        outFile << mpDataSet->channel(i)->channelId() << ";";
    }
    outFile << endl;

    // Write channel type
    outFile << ";" << ";";
    for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
    {
        outFile << mpDataSet->channel(i)->channelTypeString() << ";";
    }
    outFile << endl;


    // Write channel units
    outFile << ";" << ";";
    for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
    {
        outFile << mpDataSet->channel(i)->channelUnit() << ";";
    }
    outFile << endl;

    // Write channel description
    outFile << ";" << ";";
    for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
    {
        outFile << mpDataSet->channel(i)->channelDescription() << ";";
    }
    outFile << endl;


    // Write channel data
    unsigned int *sampleNumArr = new unsigned int[mpDataSet->numChannnels()];
    try
    {
        // Get number of samples for each channel
        for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
        {
            sampleNumArr[i] = mpDataSet->channel(i)->numSamples();
            //cout << "Channel " << i << " has " << sampleNumArr[i] << " samples\n";
        }

        unsigned int sampleCnt = 0;
        bool dataWritten;
        do
        {
            dataWritten = false;

            outFile << sampleCnt << ";";
            outFile << mpDataSet->offsetForSample(sampleCnt) << ";";
            for(unsigned int i = 0; i < mpDataSet->numChannnels(); i++)
            {                
                if(sampleCnt < sampleNumArr[i])
                {
                     outFile << mpDataSet->channel(i)->sampleString(sampleCnt) << ";";
                     dataWritten = true;
                }
                else
                {
                    outFile << ";";
                }
            }
            outFile << endl;
            sampleCnt++;
        }while(dataWritten);
    }
    catch(std::exception &e)
    {
        delete[] sampleNumArr;
        throw e;
    }

    outFile << endl;

    outFile.close();
}
